home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / fileutil.zip / CP.C < prev    next >
Text File  |  1994-07-16  |  24KB  |  965 lines

  1. /*  cp.c  -- file copying (main routines)
  2.     Copyright (C) 1989, 1990 Free Software Foundation.
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 1, or (at your option)
  7.     any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.     Written by Torbjorn Granlund and David MacKenzie. */
  19.  
  20. /* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
  21.    This port is also distributed under the terms of the
  22.    GNU General Public License as published by the
  23.    Free Software Foundation.
  24.  
  25.    Please note that this file is not identical to the
  26.    original GNU release, you should have received this
  27.    code as patch to the official release.
  28.  
  29.     Saturday, 16 July 1994  Troy Rollo (troy@cbme.unsw.EDU.AU)
  30.  
  31.         - Changed mkfifo call to depend on __BORLANDC__ as
  32.           well as S_IFIFO
  33.  */
  34.  
  35. static char RCS_Id[] =
  36.   "$Header: e:/gnu/fileutil/RCS/cp.c 1.4.0.2 90/09/19 11:18:06 tho Exp $";
  37.  
  38. static char Program_Id[] = "cp";
  39. static char RCS_Revision[] = "$Revision: 1.4.0.2 $";
  40.  
  41. #define VERSION \
  42.   "GNU %s, Version %.*s (compiled %s %s for MS-DOS)\n", Program_Id, \
  43.   (sizeof RCS_Revision - 14), (RCS_Revision + 11), __DATE__, __TIME__
  44.  
  45. #define COPYING \
  46.   "This is free software, distributed under the terms of the\n" \
  47.   "GNU General Public License.  For details, see the file COPYING.\n"
  48.  
  49. /* Yet to be done:
  50.  
  51.  * Symlink translation. */
  52.  
  53. #include <stdio.h>
  54. #include <getopt.h>
  55. #include "cp.h"
  56. #include "backupfile.h"
  57.  
  58. #ifdef MSDOS
  59. #include <assert.h>
  60.  
  61. extern enum backup_type get_version (char *version);
  62. extern char *savedir (char *dir, unsigned name_size);
  63.  
  64. #define strip_trailing_slashes(path)    strip_trailing_slashes (&path)
  65. #define is_ancestor(statb, ancestors)    0
  66. #define hash_init(module, size)
  67. #define remember_copied(path, ino, dev)    NULL
  68. #define remember_created(path)        0
  69. #define forget_all()
  70. char new_file;
  71.  
  72. #endif
  73.  
  74. #ifdef MKFIFO_MISSING
  75. /* This definition assumes that MODE has the S_IFIFO bit set. */
  76. #define mkfifo(path, mode) (mknod ((path), (mode), 0))
  77. #endif
  78.  
  79. enum backup_type get_version ();
  80. int eaccess_stat ();
  81.  
  82. /* Initial number of entries in each hash table entry's table of inodes.  */
  83. #define INITIAL_HASH_MODULE 100
  84.  
  85. /* Initial number of entries in the inode hash table.  */
  86. #define INITIAL_ENTRY_TAB_SIZE 70
  87.  
  88. /* A pointer to either lstat or stat, depending on
  89.    whether dereferencing of symlinks is done.  */
  90. #ifdef MSDOS
  91. int (*xstat) (char *, struct stat *);
  92. #else
  93. int (*xstat) ();
  94. #endif
  95.  
  96. /* The invocation name of this program.  */
  97. char *program_name;
  98.  
  99. /* If nonzero, copy all files except directories and, if not dereferencing
  100.    them, symbolic links, as if they were regular files. */
  101. int flag_copy_as_regular = 1;
  102.  
  103. /* If nonzero, dereference symbolic links (copy the files they point to). */
  104. int flag_dereference = 1;
  105.  
  106. /* If nonzero, remove existing target nondirectories. */
  107. int flag_force = 0;
  108.  
  109. /* If nonzero, query before overwriting existing targets with regular files. */
  110. int flag_interactive = 0;
  111.  
  112. /* If nonzero, give the copies the original files' permissions,
  113.    ownership, and timestamps. */
  114. int flag_preserve = 0;
  115.  
  116. /* If nonzero, copy directories recursively and copy special files
  117.    as themselves rather than copying their contents. */
  118. int flag_recursive = 0;
  119.  
  120. /* If nonzero, when copying recursively, skip any subdirectories that are
  121.    on different filesystems from the one we started on. */
  122. int flag_one_file_system = 0;
  123.  
  124. /* If nonzero, do not copy a nondirectory that has an existing destination
  125.    with the same or newer modification time. */
  126. int flag_update = 0;
  127.  
  128. /* If nonzero, display the names of the files before copying them. */
  129. int flag_verbose = 0;
  130.  
  131. /* The error code to return to the system. */
  132. int exit_status = 0;
  133.  
  134. /* The bits to preserve in created files' modes. */
  135. int umask_kill;
  136.  
  137. struct option long_opts[] =
  138. {
  139. #ifdef MSDOS
  140.   {"copying", 0, NULL, 30},
  141.   {"version", 0, NULL, 31},
  142. #endif
  143.   {"backup", 0, NULL, 'b'},
  144.   {"force", 0, NULL, 'f'},
  145.   {"interactive", 0, NULL, 'i'},
  146.   {"no-dereference", 0, &flag_dereference, 0},
  147.   {"one-file-system", 0, &flag_one_file_system, 1},
  148.   {"preserve", 0, &flag_preserve, 1},
  149.   {"recursive", 0, NULL, 'R'},
  150.   {"suffix", 1, NULL, 'S'},
  151.   {"update", 0, &flag_update, 1},
  152.   {"verbose", 0, &flag_verbose, 1},
  153.   {"version-control", 1, NULL, 'V'},
  154.   {NULL, 0, NULL, 0}
  155. };
  156.  
  157. void
  158. main (argc, argv)
  159.      int argc;
  160.      char *argv[];
  161. {
  162.   int c;
  163.   int ind;
  164.   int make_backups = 0;
  165.   char *version;
  166.  
  167.   program_name = argv[0];
  168.  
  169.   version = getenv ("SIMPLE_BACKUP_SUFFIX");
  170.   if (version)
  171.     simple_backup_suffix = version;
  172.   version = getenv ("VERSION_CONTROL");
  173.  
  174.   /* Find out the current file creation mask, to knock the right bits
  175.      when using chmod.  The creation mask is set to to be liberal, so
  176.      that created directories can be written, even if it would not
  177.      have been allowed with the mask this process was started with.  */
  178.  
  179. #ifdef MSDOS            /* not 100%ly correct ... */
  180.   umask_kill = 07777 ^ umask (0);
  181. #else
  182.   umask_kill = 0777777 ^ umask (0);
  183. #endif
  184.  
  185.   while ((c = getopt_long (argc, argv, "bdfipruvxRS:V:", long_opts, &ind))
  186.      != EOF)
  187.     {
  188.       switch (c)
  189.     {
  190.     case 0:
  191.       break;
  192.  
  193.     case 'b':
  194.       make_backups = 1;
  195.       break;
  196.  
  197.     case 'd':
  198.       flag_dereference = 0;
  199.       break;
  200.  
  201.     case 'f':
  202.       flag_force = 1;
  203.       flag_interactive = 0;
  204.       break;
  205.  
  206.     case 'i':
  207.       flag_force = 0;
  208.       flag_interactive = 1;
  209.       break;
  210.  
  211.     case 'p':
  212.       flag_preserve = 1;
  213.       break;
  214.  
  215.     case 'r':
  216.       flag_recursive = 1;
  217.       flag_copy_as_regular = 1;
  218.       break;
  219.  
  220.     case 'R':
  221.       flag_recursive = 1;
  222.       flag_copy_as_regular = 0;
  223.       break;
  224.  
  225.     case 'u':
  226.       flag_update = 1;
  227.       break;
  228.  
  229.     case 'v':
  230.       flag_verbose = 1;
  231.       break;
  232.  
  233.     case 'x':
  234.       flag_one_file_system = 1;
  235.       break;
  236.  
  237.     case 'S':
  238.       simple_backup_suffix = optarg;
  239.       break;
  240.  
  241.     case 'V':
  242.       version = optarg;
  243.       break;
  244.  
  245. #ifdef MSDOS
  246.     case 30:
  247.       fprintf (stderr, COPYING);
  248.       exit (0);
  249.       break;
  250.  
  251.     case 31:
  252.       fprintf (stderr, VERSION);
  253.       exit (0);
  254.       break;
  255. #endif
  256.  
  257.     default:
  258.       usage ((char *) 0);
  259.     }
  260.     }
  261.  
  262.   if (make_backups)
  263.     backup_type = get_version (version);
  264.  
  265.   if (flag_preserve == 1)
  266. #ifdef MSDOS            /* not 100%ly correct ... */
  267.     umask_kill = 07777;
  268. #else
  269.     umask_kill = 0777777;
  270. #endif
  271.  
  272.   /* The key difference between -d (+no-dereference) and not is the version
  273.      of `stat' to call.  */
  274.  
  275.   if (flag_dereference)
  276.     xstat = stat;
  277.   else
  278.     xstat = lstat;
  279.  
  280.   /* Allocate space for remembering copied and created files.  */
  281.  
  282.   hash_init (INITIAL_HASH_MODULE, INITIAL_ENTRY_TAB_SIZE);
  283.  
  284.   exit_status |= do_copy (argc, argv);
  285.  
  286.   exit (exit_status);
  287. }
  288.  
  289. /* Scan the arguments, and copy each by calling copy.
  290.    Return 0 if successful, 1 if any errors occur. */
  291.  
  292. int
  293. do_copy (argc, argv)
  294.      int argc;
  295.      char *argv[];
  296. {
  297.   char *target;
  298.   struct stat sb;
  299.   int new_dst = 0;
  300.   int ret = 0;
  301.  
  302.   if (optind >= argc)
  303.     usage ("missing file arguments");
  304.   if (optind >= argc - 1)
  305.     usage ("missing file argument");
  306.  
  307.   target = argv[argc - 1];
  308.  
  309.   strip_trailing_slashes (target);
  310.  
  311.   if (lstat (target, &sb))
  312.     {
  313.       if (errno != ENOENT)
  314.     {
  315.       error (0, errno, "%s", target);
  316.       return 1;
  317.     }
  318.       else
  319.     new_dst = 1;
  320.     }
  321.   else
  322.     {
  323.       struct stat sbx;
  324.  
  325.       /* If `target' is not a symlink to a nonexistent file, use
  326.      the results of stat instead of lstat, so we can copy files
  327.      into symlinks to directories. */
  328.       if (stat (target, &sbx) == 0)
  329.     sb = sbx;
  330.     }
  331.  
  332.   if (!new_dst && (sb.st_mode & S_IFMT) == S_IFDIR)
  333.     {
  334.       /* cp e_file_1...e_file_n e_dir
  335.      copy the files `e_file_1' through `e_file_n'
  336.      to the existing directory `e_dir'. */
  337.  
  338.       for (;;)
  339.     {
  340.       char *arg;
  341.       char *ap;
  342.       char *dst_path;
  343.  
  344.       arg = argv[optind];
  345.  
  346.       strip_trailing_slashes (arg);
  347.  
  348.       /* Append the last component of `arg' to `target'.  */
  349.  
  350.       ap = rindex (arg, '/');
  351.       if (ap == 0)
  352.         ap = arg;
  353.       else
  354.         ap++;
  355.       dst_path = xmalloc (strlen (target) + strlen (ap) + 2);
  356. #ifdef MSDOS
  357.       /* Here a trailing slash might still be present (needed for
  358.          stat()'ing root directories), take care of that. */
  359.       if (target[strlen(target) - 1] == '/')
  360.         stpcpy (stpcpy (dst_path, target), ap);
  361.       else
  362. #endif /* MSDOS */
  363.       stpcpy (stpcpy (stpcpy (dst_path, target), "/"), ap);
  364.  
  365.       ret |= copy (arg, dst_path, new_dst, 0, (struct dir_list *) 0);
  366.       forget_all ();
  367.  
  368.       ++optind;
  369.       if (optind == argc - 1)
  370.         break;
  371.     }
  372.       return ret;
  373.     }
  374.   else if (argc - optind == 2)
  375.     return copy (argv[optind], target, new_dst, 0, (struct dir_list *) 0);
  376.   else
  377.     usage ("when copying multiple files, last argument must be a directory");
  378. }
  379.  
  380. /* Copy the file SRC_PATH to the file DST_PATH.  The files may be of
  381.    any type.  NEW_DST should be non-zero if the file DST_PATH cannot
  382.    exist because its parent directory was just created; NEW_DST should
  383.    be zero if DST_PATH might already exist.  DEVICE is the device
  384.    number of the parent directory, or 0 if the parent of this file is
  385.    not known.  ANCESTORS points to a linked, null terminated list of
  386.    devices and inodes of parent directories of SRC_PATH.
  387.    Return 0 if successful, 1 if an error occurs. */
  388.  
  389. int
  390. copy (src_path, dst_path, new_dst, device, ancestors)
  391.      char *src_path;
  392.      char *dst_path;
  393.      int new_dst;
  394.      dev_t device;
  395.      struct dir_list *ancestors;
  396. {
  397.   struct stat src_sb;
  398.   struct stat dst_sb;
  399.   int src_mode;
  400. #ifdef MSDOS
  401.   unsigned int src_type;
  402. #else /* not MSDOS */
  403.   int src_type;
  404. #endif /* not MSDOS */
  405.   char *earlier_file;
  406.   char *dst_backup = NULL;
  407.   int dir_mode_changed = 0;
  408.  
  409.   if ((*xstat) (src_path, &src_sb))
  410.     {
  411.       error (0, errno, "%s", src_path);
  412.       return 1;
  413.     }
  414.  
  415.   /* Are we crossing a file system boundary?  */
  416.   if (flag_one_file_system && device != 0 && device != src_sb.st_dev)
  417.     return 0;
  418.  
  419.   /* We wouldn't insert a node unless nlink > 1, except that we need to
  420.      find created files so as to not copy infinitely if a directory is
  421.      copied into itself.  */
  422.  
  423.   earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
  424.  
  425.   /* Did we just create this file?  */
  426.  
  427.   if (earlier_file == &new_file)
  428.     return 0;
  429.  
  430.   src_mode = src_sb.st_mode;
  431.   src_type = src_sb.st_mode & S_IFMT;
  432.   if (flag_copy_as_regular && src_type != S_IFDIR
  433. #ifdef S_IFLNK
  434.       && src_type != S_IFLNK
  435. #endif
  436.       )
  437.     src_type = S_IFREG;
  438.  
  439.   if (src_type == S_IFDIR && !flag_recursive)
  440.     {
  441.       error (0, 0, "%s: omitting directory", src_path);
  442.       return 1;
  443.     }
  444.  
  445.   if (!new_dst)
  446.     {
  447.       if ((*xstat) (dst_path, &dst_sb))
  448.     {
  449.       if (errno != ENOENT)
  450.         {
  451.           error (0, errno, "%s", dst_path);
  452.           return 1;
  453.         }
  454.       else
  455.         new_dst = 1;
  456.     }
  457.       else
  458.     {
  459.       /* The file exists already.  */
  460. #ifdef MSDOS
  461.       if (strcmp (dst_path, src_path) == 0)
  462.         {
  463.           error (0, 0, "`%s': can't copy file to itself", src_path);
  464.           return 1;
  465.         }
  466. #else /* not MSDOS */
  467.       if (src_sb.st_ino == dst_sb.st_ino && src_sb.st_dev == dst_sb.st_dev)
  468.         {
  469.           error (0, 0, "`%s' and `%s' are the same file",
  470.              src_path, dst_path);
  471.           return 1;
  472.         }
  473. #endif /* not MSDOS */
  474.  
  475.       if (src_type != S_IFDIR)
  476.         {
  477.           if ((dst_sb.st_mode & S_IFMT) == S_IFDIR)
  478.         {
  479.           error (0, 0,
  480.              "%s: cannot overwrite directory with non-directory",
  481.              dst_path);
  482.           return 1;
  483.         }
  484.  
  485.           if (flag_update && src_sb.st_mtime <= dst_sb.st_mtime)
  486.         return 0;
  487.         }
  488.  
  489.       if (src_type == S_IFREG && !flag_force)
  490.         {
  491.           /* Treat the file as nonwritable if it lacks write permission
  492.          bits, even if we are root.  */
  493.           if (eaccess_stat (&dst_sb, W_OK) != 0
  494.           || (dst_sb.st_mode & 0222) == 0)
  495.         {
  496.           error (0, 0, "%s: Permission denied", dst_path);
  497.           return 1;
  498.         }
  499.  
  500.           if (flag_interactive)
  501.         {
  502.           fprintf (stderr, "%s: overwrite `%s'? ", program_name,
  503.                dst_path);
  504.           if (!yesno ())
  505.             return 0;
  506.         }
  507.         }
  508.  
  509.       if (backup_type != none && (dst_sb.st_mode & S_IFMT) != S_IFDIR)
  510.         {
  511.           dst_backup = find_backup_file_name (dst_path);
  512.           if (dst_backup == NULL)
  513.         error (1, 0, "virtual memory exhausted");
  514.           if (rename (dst_path, dst_backup))
  515.         {
  516.           if (errno != ENOENT)
  517.             {
  518.               error (0, errno, "cannot backup `%s'", dst_path);
  519.               free (dst_backup);
  520.               return 1;
  521.             }
  522.           else
  523.             {
  524.               free (dst_backup);
  525.               dst_backup = NULL;
  526.             }
  527.         }
  528.           new_dst = 1;
  529.         }
  530.       else if (flag_force)
  531.         {
  532.           if ((dst_sb.st_mode & S_IFMT) == S_IFDIR)
  533.         {
  534.           /* Temporarily change mode to allow overwriting. */
  535.           if (eaccess_stat (&dst_sb, W_OK | X_OK) != 0)
  536.             {
  537.               if (chmod (dst_path, 0700))
  538.             {
  539.               error (0, errno, "%s", dst_path);
  540.               return 1;
  541.             }
  542.               else
  543.             dir_mode_changed = 1;
  544.             }
  545.         }
  546.           else
  547.         {
  548.           if (unlink (dst_path) && errno != ENOENT)
  549.             {
  550.               error (0, errno, "cannot remove old link to `%s'",
  551.                  dst_path);
  552.               return 1;
  553.             }
  554.           new_dst = 1;
  555.         }
  556.         }
  557.     }
  558.     }
  559.  
  560.   if (flag_verbose)
  561.     printf ("%s -> %s\n", src_path, dst_path);
  562.  
  563.   /* Did we copy this inode somewhere else (in this command line argument)
  564.      and therefore this is a second hard link to the inode?  */
  565.  
  566.   if (!flag_dereference && src_sb.st_nlink > 1 && earlier_file)
  567.     {
  568.       if (link (earlier_file, dst_path))
  569.     {
  570.       error (0, errno, "%s", dst_path);
  571.       goto un_backup;
  572.     }
  573.       if (dst_backup)
  574.     free (dst_backup);
  575.       return 0;
  576.     }
  577.  
  578.   switch (src_type)
  579.     {
  580. #if defined(S_IFIFO) && !defined(__MSDOS__) /* Borland defines S_IFIFO
  581.                          * so programs using it will
  582.                          * compile, but mkfifo does
  583.                          * not exist, nor do fifos
  584.                          * in DOS
  585.                          */
  586.     case S_IFIFO:
  587.       if (mkfifo (dst_path, src_mode & umask_kill))
  588.     {
  589.       error (0, errno, "cannot make fifo `%s'", dst_path);
  590.       goto un_backup;
  591.     }
  592.       break;
  593. #endif
  594.  
  595. #ifndef MSDOS
  596.     case S_IFBLK:
  597.     case S_IFCHR:
  598. #ifdef S_IFSOCK
  599.     case S_IFSOCK:
  600. #endif
  601.       if (mknod (dst_path, src_mode & umask_kill, src_sb.st_rdev))
  602.     {
  603.       error (0, errno, "cannot create special file `%s'", dst_path);
  604.       goto un_backup;
  605.     }
  606.       break;
  607. #endif /* not MSDOS */
  608.  
  609.     case S_IFDIR:
  610.       {
  611.     struct dir_list *dir;
  612.  
  613.     /* If this directory has been copied before during the
  614.            recursion, there is a symbolic link to an ancestor
  615.            directory of the symbolic link.  It is impossible to
  616.            continue to copy this, unless we've got an infinite disk.  */
  617.  
  618.     if (is_ancestor (&src_sb, ancestors))
  619.       {
  620.         error (0, 0, "%s: cannot copy cyclic symbolic link", src_path);
  621.         goto un_backup;
  622.       }
  623.  
  624.     /* Insert the current directory in the list of parents.  */
  625.  
  626.     dir = (struct dir_list *) alloca (sizeof (struct dir_list));
  627. #ifdef MSDOS            /* always short of stack space ... */
  628.     if (!dir)
  629.       error (1, 0, "%s: stack overflow", src_path);
  630. #endif
  631.  
  632.     dir->parent = ancestors;
  633.     dir->ino = src_sb.st_ino;
  634.     dir->dev = src_sb.st_dev;
  635.  
  636.     if (new_dst || (dst_sb.st_mode & S_IFMT) != S_IFDIR)
  637.       {
  638.         /* Create the new directory writable and searchable, so
  639.            we can create new entries in it.  */
  640.  
  641.         if (mkdir (dst_path, 0700))
  642.           {
  643.         error (0, errno, "cannot create directory `%s'", dst_path);
  644.         goto un_backup;
  645.           }
  646.  
  647.         /* Insert the created directory's inode and device
  648.            numbers into the search structure, so that we can
  649.            avoid copying it again.  */
  650.  
  651.         if (remember_created (dst_path))
  652.           goto un_backup;
  653.       }
  654.  
  655.     /* Copy the contents of the directory.  */
  656.  
  657.     if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir))
  658.       goto err_return;
  659.       }
  660.       break;
  661.  
  662.     case S_IFREG:
  663.       if (copy_reg (src_path, dst_path))
  664.     goto un_backup;
  665.       break;
  666.  
  667. #ifdef S_IFLNK
  668.     case S_IFLNK:
  669.       {
  670.     char *link_val = (char *) alloca (src_sb.st_size + 1);
  671.  
  672.     if (readlink (src_path, link_val, src_sb.st_size) < 0)
  673.       {
  674.         error (0, errno, "cannot read symbolic link `%s'", src_path);
  675.         goto un_backup;
  676.       }
  677.     link_val[src_sb.st_size] = '\0';
  678.  
  679.     if (symlink (link_val, dst_path))
  680.       {
  681.         error (0, errno, "cannot create symbolic link `%s'", dst_path);
  682.         goto un_backup;
  683.       }
  684.       }
  685.       return 0;
  686. #endif
  687.  
  688.     default:
  689.       error (0, 0, "%s: unknown file type", src_path);
  690.       goto un_backup;
  691.     }
  692.  
  693.   if ((flag_preserve || new_dst)
  694.       && (src_type == S_IFREG || src_type == S_IFDIR))
  695.     {
  696.       if (chmod (dst_path, src_mode & umask_kill))
  697.     {
  698.       error (0, errno, "%s", dst_path);
  699.       goto err_return;
  700.     }
  701.     }
  702.   else if (dir_mode_changed)
  703.     {
  704.       /* Reset the temporarily changed mode.  */
  705.       if (chmod (dst_path, dst_sb.st_mode))
  706.     {
  707.       error (0, errno, "%s", dst_path);
  708.       goto err_return;
  709.     }
  710.     }
  711.  
  712.   /* Adjust the times (and if possible, ownership) for the copy. */
  713.  
  714.   if (flag_preserve)
  715.     {
  716.       struct utimbuf utb;
  717.  
  718.       utb.actime = src_sb.st_atime;
  719.       utb.modtime = src_sb.st_mtime;
  720.  
  721.       if (utime (dst_path, &utb))
  722.     {
  723.       error (0, errno, "%s", dst_path);
  724.       goto err_return;
  725.     }
  726.  
  727.       if (chown (dst_path, src_sb.st_uid, src_sb.st_gid) && errno != EPERM)
  728.     {
  729.       error (0, errno, "%s", dst_path);
  730.       goto err_return;
  731.     }
  732.     }
  733.  
  734.   if (dst_backup)
  735.     free (dst_backup);
  736.   return 0;
  737.  
  738. err_return:
  739.   if (dst_backup)
  740.     free (dst_backup);
  741.   return 1;
  742.  
  743. un_backup:
  744.   if (dst_backup)
  745.     {
  746.       if (rename (dst_backup, dst_path))
  747.     error (0, errno, "cannot un-backup `%s'", dst_path);
  748.       free (dst_backup);
  749.     }
  750.   return 1;
  751. }
  752.  
  753. /* Read the contents of the directory SRC_PATH_IN, and recursively
  754.    copy the contents to DST_PATH_IN.  NEW_DST is non-zero if
  755.    DST_PATH_IN is a directory that was created previously in the
  756.    recursion.   SRC_SB and ANCESTORS describe SRC_PATH_IN.
  757.    Return 0 if successful, -1 if an error occurs. */
  758.  
  759. int
  760. copy_dir (src_path_in, dst_path_in, new_dst, src_sb, ancestors)
  761.      char *src_path_in;
  762.      char *dst_path_in;
  763.      int new_dst;
  764.      struct stat *src_sb;
  765.      struct dir_list *ancestors;
  766. {
  767.   char *name_space;
  768.   char *namep;
  769.   char *src_path;
  770.   char *dst_path;
  771.   int ret = 0;
  772.  
  773.   errno = 0;
  774. #ifdef MSDOS
  775.   assert (src_sb->st_size < 0xffffL);
  776.   name_space = savedir (src_path_in, (size_t) src_sb->st_size);
  777. #else
  778.   name_space = savedir (src_path_in, src_sb->st_size);
  779. #endif
  780.   if (name_space == 0)
  781.     {
  782.       if (errno)
  783.     {
  784.       error (0, errno, "%s", src_path_in);
  785.       return -1;
  786.     }
  787.       else
  788.     error (1, 0, "virtual memory exhausted");
  789.     }
  790.  
  791.   namep = name_space;
  792.   while (*namep != '\0')
  793.     {
  794.       int fn_length = strlen (namep) + 1;
  795.  
  796.       dst_path = xmalloc (strlen (dst_path_in) + fn_length + 1);
  797.       src_path = xmalloc (strlen (src_path_in) + fn_length + 1);
  798.  
  799.       stpcpy (stpcpy (stpcpy (src_path, src_path_in), "/"), namep);
  800.       stpcpy (stpcpy (stpcpy (dst_path, dst_path_in), "/"), namep);
  801.  
  802.       ret |= copy (src_path, dst_path, new_dst, src_sb->st_dev, ancestors);
  803.  
  804.       /* Free the memory for `src_path'.  The memory for `dst_path'
  805.      cannot be deallocated, since it is used to create multiple
  806.      hard links.  */
  807.  
  808.       free (src_path);
  809.  
  810.       namep += fn_length;
  811.     }
  812.   free (name_space);
  813.   return -ret;
  814. }
  815.  
  816. /* Copy a regular file from SRC_PATH to DST_PATH.  Large blocks of zeroes,
  817.    as well as holes in the source file, are made into holes in the
  818.    target file.  (Holes are read as zeroes by the `read' system call.)
  819.    Return 0 if successful, -1 if an error occurred. */
  820.  
  821. int
  822. copy_reg (src_path, dst_path)
  823.      char *src_path;
  824.      char *dst_path;
  825. {
  826.   char *buf;
  827.   int buf_size;
  828.   int target_desc;
  829.   int source_desc;
  830.   int n_read;
  831.   int n_written;
  832.   struct stat sb;
  833.   int return_val = 0;
  834.   long n_read_total = 0;
  835.   char *cp;
  836.   int *ip;
  837.   int last_write_made_hole = 0;
  838.  
  839. #ifdef MSDOS
  840.   source_desc = open (src_path, O_BINARY | O_RDONLY);
  841. #else
  842.   source_desc = open (src_path, O_RDONLY);
  843. #endif
  844.   if (source_desc < 0)
  845.     {
  846.       error (0, errno, "%s", src_path);
  847.       return -1;
  848.     }
  849.  
  850.   /* Create the new regular file with small permissions initially,
  851.      to not create a security hole.  */
  852.  
  853. #ifdef MSDOS
  854.   target_desc = open (dst_path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0600);
  855. #else
  856.   target_desc = open (dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
  857. #endif
  858.   if (target_desc < 0)
  859.     {
  860.       error (0, errno, "cannot create regular file `%s'", dst_path);
  861.       return_val = -1;
  862.       goto ret2;
  863.     }
  864.  
  865.   /* Find out the appropriate buffer length.  */
  866.  
  867.   if (fstat (target_desc, &sb))
  868.     {
  869.       error (0, errno, "%s", dst_path);
  870.       return_val = -1;
  871.       goto ret;
  872.     }
  873.  
  874.   buf_size = ST_BLKSIZE (sb);
  875.  
  876.   /* Make a buffer with space for a sentinel at the end.  */
  877.  
  878.   buf = (char *) alloca (buf_size + sizeof (int));
  879. #ifdef MSDOS
  880.   if (!buf)
  881.     error (2, 0, "%s: stack overflow", src_path);
  882. #endif
  883.  
  884.   for (;;)
  885.     {
  886.       n_read = read (source_desc, buf, buf_size);
  887.       if (n_read < 0)
  888.     {
  889.       error (0, errno, "%s", src_path);
  890.       return_val = -1;
  891.       goto ret;
  892.     }
  893.       if (n_read == 0)
  894.     break;
  895.  
  896. #ifdef MSDOS
  897.       n_read_total += (long) n_read;
  898. #else
  899.       n_read_total += n_read;
  900. #endif
  901.  
  902.       buf[n_read] = 1;        /* Sentinel to stop loop.  */
  903.  
  904.       /* Find first non-zero *word*, or the word with the sentinel.  */
  905.  
  906.       ip = (int *) buf;
  907.       while (*ip++ == 0)
  908.     ;
  909.  
  910.       /* Find the first non-zero *byte*, or the sentinel.  */
  911.  
  912.       cp = (char *) (ip - 1);
  913.       while (*cp++ == 0)
  914.     ;
  915.  
  916.       /* If we found the sentinel, the whole input block was zero,
  917.      and we can make a hole.  */
  918.  
  919.       if (cp > buf + n_read)
  920.     {
  921.       /* Make a hole.  */
  922.       if (lseek (target_desc, (off_t) n_read, L_INCR) < 0L)
  923.         {
  924.           error (0, errno, "%s", dst_path);
  925.           return_val = -1;
  926.           goto ret;
  927.         }
  928.       last_write_made_hole = 1;
  929.     }
  930.       else
  931.     {
  932.       n_written = write (target_desc, buf, n_read);
  933.       if (n_written < n_read)
  934.         {
  935.           error (0, errno, "%s", dst_path);
  936.           return_val = -1;
  937.           goto ret;
  938.         }
  939.       last_write_made_hole = 0;
  940.     }
  941.     }
  942.  
  943.   /* If the file ends with a `hole', something needs to be written at
  944.      the end.  Otherwise the kernel would truncate the file at the end
  945.      of the last write operation.  */
  946.  
  947.   if (last_write_made_hole)
  948.     {
  949.       /* Seek backwards one character and write a null.  */
  950.       if (lseek (target_desc, (off_t) -1, L_INCR) < 0L
  951.       || write (target_desc, "", 1) != 1)
  952.     {
  953.       error (0, errno, "%s", dst_path);
  954.       return_val = -1;
  955.     }
  956.     }
  957.  
  958. ret:
  959.   close (target_desc);
  960. ret2:
  961.   close (source_desc);
  962.  
  963.   return return_val;
  964. }
  965.